Component({
  properties: {
    innerRadius: { type: Number, value: 60 },    // 内环半径(rpx)
    outerRadius: { type: Number, value: 100 },   // 外环半径(rpx)
    title: { type: String, value: '总设备' },
    subtitle: { type: String, value: '3000' },
    titleColor: { type: String, value: '#4dabff' },
    subtitleColor: { type: String, value: '#4dabff' },
    titleSize: { type: Number, value: 28 },     // 标题字号(rpx)
    subtitleSize: { type: Number, value: 39 },  // 副标题字号(rpx)
    data: { type: Array, value: [] },
    canvasHeight: { type: Number, value: 400 }  // 画布高度(rpx)
  },

  observers: {
    '**': function () {
      wx.nextTick(() => this.draw())
    }
  },

  methods: {
    async getCanvasContext() {
      const res = await new Promise(resolve => {
        wx.createSelectorQuery()
          .in(this)
          .select('#ringChart')
          .fields({ node: true, size: true })
          .exec(resolve)
      })
      const canvas = res[0].node
      const systemInfo = wx.getWindowInfo()
      
      // 设置物理像素尺寸（解决模糊问题）[2,7](@ref)
      canvas.width = res[0].width * systemInfo.pixelRatio
      canvas.height = res[0].height * systemInfo.pixelRatio
      
      const ctx = canvas.getContext('2d')
      ctx.scale(systemInfo.pixelRatio, systemInfo.pixelRatio) // 缩放坐标系
      return ctx
    },

    async draw() {
      const ctx = await this.getCanvasContext()
      if (!ctx) return
      
      // 清空画布
      ctx.clearRect(0, 0, ctx.canvas.width / ctx.getTransform().a, ctx.canvas.height / ctx.getTransform().a)

      // 配置计算
      const systemInfo = wx.getWindowInfo()
      const rpxRatio = systemInfo.windowWidth / 750
      const config = {
        ringWidth: (this.properties.outerRadius - this.properties.innerRadius) * rpxRatio,
        actualOuterRadius: this.properties.outerRadius * rpxRatio,
        actualInnerRadius: this.properties.innerRadius * rpxRatio,
        centerX: (ctx.canvas.width / ctx.getTransform().a) / 2,
        centerY: (ctx.canvas.height / ctx.getTransform().a) / 2,
        titleSize: this.properties.titleSize * rpxRatio,
        subtitleSize: this.properties.subtitleSize * rpxRatio
      }

      // 环形图绘制逻辑
      const total = this.data.data.reduce((sum, item) => sum + item.value, 0)
      let startAngle = 0

      // 外环绘制
      this.data.data.forEach(item => {
        const angle = (item.value / total) * Math.PI * 2
        const gradient = this.createSegmentGradient(
          ctx,
          config.centerX,
          config.centerY,
          config.actualOuterRadius,
          startAngle,
          angle,
          item.colorStart,
          item.colorEnd
        )
        
        this.drawSegment(
          ctx,
          config.centerX,
          config.centerY,
          config.actualOuterRadius,
          startAngle,
          angle,
          gradient,
          config.ringWidth + 1
        )
        startAngle += angle
      })

      // 内环覆盖
      startAngle = 0
      this.data.data.forEach(item => {
        const angle = (item.value / total) * Math.PI * 2
        this.drawSegment(
          ctx,
          config.centerX,
          config.centerY,
          config.actualInnerRadius,
          startAngle,
          angle,
          '#FFFFFF',
          config.ringWidth + 2
        )
        startAngle += angle
      })

      // 标注线
      startAngle = 0
      this.data.data.forEach(item => {
        const angle = (item.value / total) * Math.PI * 2
        this.drawLabelLine(
          ctx,
          config.centerX,
          config.centerY,
          startAngle + angle / 2,
          config.actualOuterRadius,
          item.colorStart,
          item.label,
          item.value,
          rpxRatio,
          ctx.canvas.width / ctx.getTransform().a,
          ctx.canvas.height / ctx.getTransform().a
        )
        startAngle += angle
      })

      // 中心文字
      ctx.shadowOffsetX = 0.5
      ctx.shadowOffsetY = 0.5
      ctx.shadowBlur = 1
      ctx.shadowColor = 'rgba(0,0,0,0.02)'
      this.drawCenterText(ctx, config)
    },

    createSegmentGradient(ctx, centerX, centerY, radius, startAngle, angle, colorStart, colorEnd) {
      const startPoint = {
        x: centerX + Math.cos(startAngle) * radius,
        y: centerY + Math.sin(startAngle) * radius
      }
      const endPoint = {
        x: centerX + Math.cos(startAngle + angle) * radius,
        y: centerY + Math.sin(startAngle + angle) * radius
      }

      const grd = ctx.createLinearGradient(
        startPoint.x, startPoint.y,
        endPoint.x, endPoint.y
      )
      grd.addColorStop(0, colorStart)
      grd.addColorStop(1, colorEnd)
      return grd
    },

    drawSegment(ctx, x, y, radius, startAngle, angle, color, lineWidth) {
      const gapRadians = 0.0087
      
      // 主线段
      ctx.beginPath()
      ctx.arc(x, y, radius, startAngle + gapRadians, startAngle + angle - gapRadians)
      ctx.strokeStyle = color
      ctx.lineWidth = lineWidth
      ctx.stroke()

      // 白色分隔线
      ctx.beginPath()
      ctx.arc(x, y, radius, startAngle + angle - gapRadians, startAngle + angle + gapRadians)
      ctx.strokeStyle = '#FFFFFF'
      ctx.lineWidth = lineWidth + 4
      ctx.stroke()
    },

    drawLabelLine(ctx, x, y, angle, actualRadius, color, label, value, rpxRatio, canvasWidth, canvasHeight) {
      const ringWidth = (this.properties.outerRadius - this.properties.innerRadius) * rpxRatio
      const lineStartX = x + Math.cos(angle) * (actualRadius + ringWidth / 2 + 0.5)
      const lineStartY = y + Math.sin(angle) * (actualRadius + ringWidth / 2 + 0.5)

      const direction = Math.cos(angle) > 0 ? 1 : -1
      const maxLength = direction > 0 ? canvasWidth - lineStartX - 80 : lineStartX - 40
      const lineLength = Math.min(maxLength, 150 * rpxRatio)

      if (maxLength < 20) return

      const lineEndX = lineStartX + lineLength * direction
      const textX = lineEndX + 8 * direction
      const textY = Math.max(20, Math.min(lineStartY + 4 * rpxRatio, canvasHeight - 20))

      // 绘制指示线
      ctx.beginPath()
      ctx.moveTo(lineStartX, lineStartY)
      ctx.lineTo(lineEndX, lineStartY)
      ctx.strokeStyle = color
      ctx.lineWidth = 1
      ctx.stroke()

      // 绘制标签
      ctx.font = `${24 * rpxRatio}px sans-serif`
      ctx.fillStyle = color
      ctx.textAlign = direction > 0 ? 'left' : 'right'
      this.wrapText(ctx, label, textX, textY, direction > 0 ? canvasWidth - textX - 10 : textX - 10, 16 * rpxRatio)

      // 数值绘制
      ctx.font = `${20 * rpxRatio}px sans-serif`
      const midX = (lineStartX + lineEndX) / 2
      const baseY = lineStartY - 18 * rpxRatio
      const textMetrics = ctx.measureText(`${value}`)

      ctx.save()
      ctx.textAlign = 'center'
      if (textMetrics.width > lineLength * 0.9) {
        this.wrapText(ctx, `${value}`, midX - (lineLength * 0.9) / 2, baseY + 20 * rpxRatio, lineLength * 0.9, 20 * rpxRatio, true)
      } else {
        ctx.fillText(`${value}`, midX, baseY + 10 * rpxRatio)
      }
      ctx.restore()
    },

    wrapText(ctx, text, x, y, maxWidth, lineHeight, centerMode = false) {
      const words = text.split('')
      let line = ''
      let currentY = y

      words.forEach((word, index) => {
        const testLine = line + word
        const metrics = ctx.measureText(testLine)
        
        if (metrics.width > maxWidth && index > 0) {
          ctx.fillText(line, centerMode ? x + maxWidth/2 : x, currentY)
          line = word
          currentY += lineHeight
        } else {
          line = testLine
        }
      })
      
      ctx.fillText(line, centerMode ? x + maxWidth/2 : x, currentY)
    },

    drawCenterText(ctx, config) {
      ctx.fillStyle = this.properties.titleColor
      ctx.font = `${config.titleSize}px sans-serif`
      ctx.textAlign = 'center'
      ctx.textBaseline = 'middle'
      ctx.fillText(this.properties.title, config.centerX, config.centerY - config.titleSize/2)

      ctx.fillStyle = this.properties.subtitleColor
      ctx.font = `${config.subtitleSize}px sans-serif`
      ctx.fillText(this.properties.subtitle, config.centerX, config.centerY + config.subtitleSize/2)
    }
  }
})